// ==============================================================================
//
// software development kit v 3.0
// shared structs unit
//
// copyright (c) 2008-2009 gear pair games
//
// copyright and license exceptions noted in source
//
// ==============================================================================
unit structs;

interface

uses
  types,
  math;

type
(* ******************************************************************************
                             draw structs ( render.dil )
****************************************************************************** *)
// structure Sprite draw
  structSprite = packed record
    pos : vec3;
    size : vec2;
    rot : vec3;
    param : int;
  end;
(* ******************************************************************************
                             std structs ( default )
****************************************************************************** *)

// std::intRec:
  intRec = record
    case uint of
     0 :
     ( asByte : array [ 1 .. 4 ] of byte );
     1 :
     ( asShort : array [ 1 .. 2 ] of short );
     2 :
     ( asInt : int );
     3 :
     ( asHandle : uint );
     4 :
     ( asVoid : void );
     5 :
     ( asPchar : pchar );
  end;

// std::twoIntRec
  twoIntRec = array [ 0 .. 1 ] of intRec;
  ptwoIntRec = ^twoIntRec;

// std::structMsg
  structMsg = record
    msg : ushort;
    case bool of
     false :
     ( asHandle : handle;
     asParamOne, asParamTwo : int );
     true :
     ( data : array [ 1 .. 6 ] of ushort );
  end;

  pstructMsg = ^structMsg; // void to struct

// advance
  list = class
  private { private }
    fCount : int;
    fItems : array of void;
    fItmSize : ushort;
  protected { protected }
// list::getCount
    function getCount : ushort;
// list::getItem
    function getItem( const inInd : ushort ) : void;
// list::setCount
    procedure setCount( const Value : ushort );
// list::setItem
    procedure setItem( const inInd : ushort; const Value : void );
  public { public }
    constructor create( inCnt, inSizeItem : ushort );
// list::init
    procedure init( const inSize, inSizeItem : ushort );
// list::get
    property get[ const inInd : ushort ] : void read getItem write setItem; default;
// list::free
    procedure free( const inClearMem : bool );
// list::count
    property count : ushort read getCount write setCount;
// list::add
    procedure add( const inItem : void );
// list::del
    procedure del( const inItem : int; const inFreeBlock : bool ); overload;
// list::del
    procedure del( const inItem : void; const inFreeBlock : bool ); overload;
// list::swap
    procedure swap( const inInd1, inInd2 : ushort );
// list::indexOf
    function indexOf( const inItem : void ) : int;
  end;

// listStack
  listStack = class( list )
  private { private }
    fPos : ushort;
  protected { protected }
// listStack::getItem
    function getItem( const inInd : ushort ) : void;
  public { public }
// listStack::create
    constructor create( inSize, inSizeItem : ushort );
// listStack::add
    procedure add( const inItem : void );
// listStack::allocAll
    procedure allocAll;
    property pos : ushort read fPos;
    property get[ const inInd : ushort ] : void read getItem write setItem; default;
  end;

implementation

// private const
const
  msgErrCount = 'index item does not exist';
{ list }

// list::create
procedure list.add( const inItem : void );
begin
  inc( fCount );
  setlength( fItems, fCount );
  fItems[ fCount - 1 ] := inItem;
end;

constructor list.create( inCnt, inSizeItem : ushort );
begin
  inherited create;
// init list
  init( inCnt, inSizeItem );
end;

// list::del
procedure list.del( const inItem : void; const inFreeBlock : bool );
begin
// find by addr and call function del
  del( indexOf( inItem ), inFreeBlock );
end;

procedure list.del( const inItem : int; const inFreeBlock : bool );
var
  j : int;
begin
  if ( inItem = - 1 ) then
    exit;

// need free mem ?
  if inFreeBlock then
    freemem( fItems[ inItem ], fItmSize );
// swap
  for j := inItem to fCount - 2 do
    swap( j, j + 1 );
// new lengh -1
  count := fCount - 1;
end;

// list::free
procedure list.free( const inClearMem : bool );
var
  j : int;
begin
  if inClearMem then
    for j := 0 to fCount - 1 do
     freemem( fItems[ j ], fItmSize );
 // free arr
  setlength( fItems, 0 );
  fItems := nil;
 // free self
  inherited free;
end;

// list::getCount
function list.getCount : ushort;
begin
  result := fCount;
end;

// list::getItem
function list.getItem( const inInd : ushort ) : void;
begin
  assert( ( fCount > inInd ), msgErrCount );
  result := fItems[ inInd ];
end;

// list::init
procedure list.init( const inSize, inSizeItem : ushort );
begin
  fItmSize := inSizeItem;
  count := inSize;
end;

// list::setCount
procedure list.setCount( const Value : ushort );
begin
  if fCount = Value then
    exit;
  fCount := Value;
  setlength( fItems, fCount );
end;

// list::setItem
procedure list.setItem( const inInd : ushort; const Value : void );
begin
  assert( ( fCount > inInd ), msgErrCount );
  fItems[ inInd ] := Value;
end;

// list::swap
procedure list.swap( const inInd1, inInd2 : ushort );
var
  temp : void;
begin
  temp := fItems[ inInd1 ]; // copy to temp
  fItems[ inInd1 ] := fItems[ inInd2 ]; // swap - 2
  fItems[ inInd2 ] := temp; // swap - 1
end;

// list::indexOf
function list.indexOf( const inItem : void ) : int;
begin
  for result := 0 to fCount - 1 do
    if fItems[ result ] = inItem then
     exit;
// exit value
  result := - 1;
end;

{ listStack }

procedure listStack.add( const inItem : void );
begin
  inc( fPos );
  assert( fPos < fCount, '#' );
  move( inItem^, fItems[ fPos - 1 ]^, fItmSize );
end;

procedure listStack.allocAll;
var
  i : int;
begin
  for i := 0 to count - 1 do
    fItems[ i ] := AllocMem( fItmSize );
end;

constructor listStack.create( inSize, inSizeItem : ushort );
begin
  fPos := 0;
  inherited;
end;

function listStack.getItem( const inInd : ushort ) : void;
begin
  result := inherited getItem( inInd );
  dec( fPos );
end;

end.
